using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using System.Linq;

namespace DynamicFrom
{
    /// <summary>
    /// 类型配置
    /// </summary>
    public class TypeConfiguration
    {
        /// <summary>
        /// 类名，使用标准.NET格式：Namespace.TypeName, AssemblyName
        /// 例如：DynamicFrom.Product, DynamicFrom
        /// </summary>
        public string ClassName { get; set; }
        /// <summary>
        /// 对应的JSON文件路径（相对于Config文件夹的路径）
        /// </summary>
        public string JsonFilePath { get; set; }
    }

    /// <summary>
    /// 配置管理器
    /// </summary>
    public static class ConfigManager
    {
        private static readonly string ConfigFileName = "Config.json";
        private static readonly string ConfigFolderName = "Config";
        private static TypeConfiguration _config;
        private static string _currentConfigFile;

        /// <summary>
        /// 获取配置文件夹路径
        /// </summary>
        /// <returns>配置文件夹的完整路径</returns>
        public static string GetConfigFolderPath()
        {
            // 先检查应用程序根目录下是否有Config文件夹
            string configFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigFolderName);
            if (Directory.Exists(configFolder))
            {
                return configFolder;
            }

            // 检查当前工作目录
            configFolder = Path.Combine(Directory.GetCurrentDirectory(), ConfigFolderName);
            if (Directory.Exists(configFolder))
            {
                return configFolder;
            }

            // 检查上级目录
            DirectoryInfo parent = Directory.GetParent(Directory.GetCurrentDirectory());
            if (parent != null)
            {
                configFolder = Path.Combine(parent.FullName, ConfigFolderName);
                if (Directory.Exists(configFolder))
                {
                    return configFolder;
                }
            }

            // 如果找不到，创建一个默认的Config文件夹
            configFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigFolderName);
            Directory.CreateDirectory(configFolder);
            return configFolder;
        }

        /// <summary>
        /// 获取Config目录中所有配置文件
        /// </summary>
        /// <returns>配置文件列表</returns>
        public static List<string> GetAllConfigFiles()
        {
            string configFolderPath = GetConfigFolderPath();

            // 获取所有json文件
            var files = Directory.GetFiles(configFolderPath, "*.json")
                .Select(f => Path.GetFileName(f))
                .Where(f => f.EndsWith("Config.json", StringComparison.OrdinalIgnoreCase))
                .ToList();

            return files;
        }

        /// <summary>
        /// 加载配置文件
        /// </summary>
        public static TypeConfiguration LoadConfig()
        {
            if (_config != null)
                return _config;

            // 先在Config目录下查找
            string configFolderPath = GetConfigFolderPath();
            string configPath = Path.Combine(configFolderPath, ConfigFileName);

            // 如果Config目录中没有找到，则查找执行目录或上级目录
            if (!File.Exists(configPath))
            {
                configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConfigFileName);

                if (!File.Exists(configPath))
                {
                    // 尝试查找项目目录
                    string projectDir = Directory.GetCurrentDirectory();
                    configPath = Path.Combine(projectDir, ConfigFileName);

                    if (!File.Exists(configPath))
                    {
                        // 尝试向上一级目录
                        DirectoryInfo parent = Directory.GetParent(projectDir);
                        if (parent != null)
                        {
                            configPath = Path.Combine(parent.FullName, ConfigFileName);
                        }
                    }
                }
            }
            try
            {
                if (!File.Exists(configPath))
                {
                    throw new FileNotFoundException($"找不到配置文件: {ConfigFileName}");
                }

                // 检测文件编码并读取内容
                System.Text.Encoding fileEncoding = DetectFileEncoding(configPath);
                string jsonContent = File.ReadAllText(configPath, fileEncoding);

                _config = JsonConvert.DeserializeObject<TypeConfiguration>(jsonContent);
                return _config;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载配置文件时出错: {ex.Message}", "配置加载错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                throw ex;
            }
        }



        /// <summary>
        /// 根据配置动态加载类型
        /// </summary>
        /// <returns>动态加载的类型</returns>
        /// <remarks>
        /// 此方法从配置文件中读取ClassName，然后使用反射动态加载类型。
        /// 使用标准的.NET类型名称格式：Namespace.TypeName, AssemblyName
        /// 支持从当前程序集或外部DLL加载类型。
        /// 如果找不到指定程序集，将尝试多种方式加载，包括：
        /// 1. 检查已加载的程序集
        /// 2. 从多个路径搜索并加载外部DLL（应用程序根目录、当前工作目录、上级目录等）
        /// 3. 按名称加载程序集
        /// 4. 回退到当前执行程序集
        /// </remarks>
        public static Type LoadTypeFromConfig()
        {
            try
            {
                // 加载配置
                TypeConfiguration config = LoadConfig();
                if (config == null)
                {
                    throw new Exception("无法加载类型配置");
                }

                if (string.IsNullOrWhiteSpace(config.ClassName))
                {
                    throw new Exception("ClassName配置不能为空");
                }

                // 使用Type.GetType方法加载类型
                Type type = Type.GetType(config.ClassName);

                // 如果Type.GetType无法找到类型，尝试从已加载的程序集中查找
                if (type == null)
                {
                    type = FindTypeInLoadedAssemblies(config.ClassName);
                }

                // 如果仍未找到，尝试加载程序集
                if (type == null)
                {
                    type = LoadTypeFromAssembly(config.ClassName);
                }

                if (type == null)
                {
                    throw new Exception($"无法加载类型: {config.ClassName}");
                }

                return type;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载类型时出错: {ex.Message}", "类型加载错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                throw;
            }
        }

        /// <summary>
        /// 从已加载的程序集中查找类型
        /// </summary>
        /// <param name="typeName">类型名称</param>
        /// <returns>找到的类型，如果找不到则返回null</returns>
        private static Type FindTypeInLoadedAssemblies(string typeName)
        {
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                Type type = assembly.GetType(typeName);
                if (type != null)
                {
                    return type;
                }
            }
            return null;
        }

        /// <summary>
        /// 从程序集加载类型
        /// </summary>
        /// <param name="typeName">类型名称</param>
        /// <returns>找到的类型，如果找不到则返回null</returns>
        private static Type LoadTypeFromAssembly(string typeName)
        {
            try
            {
                // 解析类型名称，提取程序集名称
                string[] parts = typeName.Split(',');
                if (parts.Length >= 2)
                {
                    string fullTypeName = parts[0].Trim();
                    string assemblyName = parts[1].Trim();

                    // 尝试加载程序集
                    Assembly assembly = null;

                    // 先尝试按名称加载
                    try
                    {
                        assembly = Assembly.Load(assemblyName);
                    }
                    catch
                    {
                        // 如果按名称加载失败，尝试从文件加载
                        assembly = LoadAssemblyFromPath($"{assemblyName}.dll");
                    }

                    if (assembly != null)
                    {
                        return assembly.GetType(fullTypeName);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"LoadTypeFromAssembly error: {ex.Message}");
            }

            return null;
        }

        /// <summary>
        /// 从多个可能的路径加载程序集
        /// </summary>
        /// <param name="assemblyPath">程序集路径（可以是相对路径或绝对路径）</param>
        /// <returns>加载的程序集，如果找不到则返回null</returns>
        private static Assembly LoadAssemblyFromPath(string assemblyPath)
        {
            // 如果是绝对路径，直接尝试加载
            if (Path.IsPathRooted(assemblyPath))
            {
                if (File.Exists(assemblyPath))
                {
                    return Assembly.LoadFrom(assemblyPath);
                }
                return null;
            }

            // 搜索路径列表（按优先级排序）
            var searchPaths = new List<string>
            {
                AppDomain.CurrentDomain.BaseDirectory,                    // 应用程序根目录
                Directory.GetCurrentDirectory(),                          // 当前工作目录
                Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), // 上级目录
                Path.GetDirectoryName(Directory.GetCurrentDirectory())    // 当前工作目录的上级目录
            };

            // 去重并过滤掉null值
            searchPaths = searchPaths.Where(p => !string.IsNullOrEmpty(p)).Distinct().ToList();

            // 在每个路径中搜索程序集
            foreach (string searchPath in searchPaths)
            {
                string fullPath = Path.Combine(searchPath, assemblyPath);
                if (File.Exists(fullPath))
                {
                    try
                    {
                        return Assembly.LoadFrom(fullPath);
                    }
                    catch (Exception ex)
                    {
                        // 记录加载失败，但继续尝试其他路径
                        System.Diagnostics.Debug.WriteLine($"Failed to load assembly from {fullPath}: {ex.Message}");
                        continue;
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// 创建配置中指定类型的实例
        /// </summary>
        /// <returns>创建的实例</returns>
        /// <remarks>
        /// 此方法首先加载配置中指定的类型，然后使用Activator.CreateInstance创建该类型的实例。
        /// 要求目标类型必须有一个无参数的公共构造函数。
        /// </remarks>
        public static object CreateInstanceFromConfig()
        {
            Type type = LoadTypeFromConfig();
            return Activator.CreateInstance(type);
        }

        /// <summary>
        /// 从JSON文件创建配置中指定类型的实例
        /// </summary>
        /// <returns>从JSON反序列化的实例，如果JSON文件不存在或无法解析则返回新实例</returns>
        /// <remarks>
        /// 此方法首先尝试从配置中指定的JSON文件加载数据并反序列化为指定类型。
        /// 如果JSON文件不存在或反序列化失败，则创建类型的新实例。
        /// 当JsonFilePath不是绝对路径时，会向上递归查找文件。
        /// </remarks>
        public static object CreateInstanceFromJson()
        {
            try
            {
                // 加载类型
                Type type = LoadTypeFromConfig();
                TypeConfiguration config = LoadConfig();

                // 检查JSON文件路径是否有效
                if (string.IsNullOrEmpty(config.JsonFilePath))
                {
                    return Activator.CreateInstance(type);
                }

                string jsonFilePath = FindJsonFile(config.JsonFilePath);

                // 检查文件是否存在
                if (string.IsNullOrEmpty(jsonFilePath) || !File.Exists(jsonFilePath))
                {
                    return Activator.CreateInstance(type);
                }

                // 检测文件编码并读取内容
                System.Text.Encoding fileEncoding = DetectFileEncoding(jsonFilePath);
                string jsonContent = File.ReadAllText(jsonFilePath, fileEncoding);

                // 反序列化为指定类型
                object instance = JsonConvert.DeserializeObject(jsonContent, type);

                // 如果反序列化失败，则创建新实例
                if (instance == null)
                {
                    instance = Activator.CreateInstance(type);
                }

                return instance;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"从JSON创建实例时出错: {ex.Message}", "JSON反序列化错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

                // 出错时，尝试创建一个新实例
                return CreateInstanceFromConfig();
            }
        }

        /// <summary>
        /// 检测文件编码
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>检测到的编码，如果无法检测则返回UTF8</returns>
        private static System.Text.Encoding DetectFileEncoding(string filePath)
        {
            try
            {
                byte[] bytes = File.ReadAllBytes(filePath);
                
                // 检查BOM标记
                if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
                {
                    return System.Text.Encoding.UTF8; // UTF-8 with BOM
                }
                else if (bytes.Length >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE)
                {
                    return System.Text.Encoding.Unicode; // UTF-16 LE
                }
                else if (bytes.Length >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF)
                {
                    return System.Text.Encoding.BigEndianUnicode; // UTF-16 BE
                }
                
                // 尝试检测是否为UTF-8（无BOM）
                bool isUtf8 = true;
                for (int i = 0; i < bytes.Length; i++)
                {
                    if (bytes[i] < 0x80)
                    {
                        // ASCII字符，继续
                        continue;
                    }
                    else if (bytes[i] < 0xC0)
                    {
                        // 无效的UTF-8序列
                        isUtf8 = false;
                        break;
                    }
                    else if (bytes[i] < 0xE0)
                    {
                        // 2字节UTF-8序列
                        if (i + 1 >= bytes.Length || (bytes[i + 1] & 0xC0) != 0x80)
                        {
                            isUtf8 = false;
                            break;
                        }
                        i++;
                    }
                    else if (bytes[i] < 0xF0)
                    {
                        // 3字节UTF-8序列
                        if (i + 2 >= bytes.Length || (bytes[i + 1] & 0xC0) != 0x80 || (bytes[i + 2] & 0xC0) != 0x80)
                        {
                            isUtf8 = false;
                            break;
                        }
                        i += 2;
                    }
                    else
                    {
                        isUtf8 = false;
                        break;
                    }
                }
                
                if (isUtf8)
                {
                    return System.Text.Encoding.UTF8;
                }
                
                // 默认返回系统默认编码
                return System.Text.Encoding.Default;
            }
            catch
            {
                // 如果检测失败，返回UTF-8
                return System.Text.Encoding.UTF8;
            }
        }

        /// <summary>
        /// 查找JSON文件，支持相对路径的递归查找
        /// </summary>
        /// <param name="jsonFilePath">JSON文件路径（可以是相对路径或绝对路径）</param>
        /// <returns>找到的完整文件路径，如果找不到则返回null</returns>
        private static string FindJsonFile(string jsonFilePath)
        {
            // 如果是绝对路径，直接检查文件是否存在
            if (Path.IsPathRooted(jsonFilePath))
            {
                return File.Exists(jsonFilePath) ? jsonFilePath : null;
            }

            // 搜索路径列表（按优先级排序）
            var searchPaths = new List<string>
            {
                AppDomain.CurrentDomain.BaseDirectory,                    // 应用程序根目录
                Directory.GetCurrentDirectory(),                          // 当前工作目录
                Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), // 上级目录
                Path.GetDirectoryName(Directory.GetCurrentDirectory())    // 当前工作目录的上级目录
            };

            // 去重并过滤掉null值
            searchPaths = searchPaths.Where(p => !string.IsNullOrEmpty(p)).Distinct().ToList();

            // 在每个路径中搜索JSON文件
            foreach (string searchPath in searchPaths)
            {
                string fullPath = Path.Combine(searchPath, jsonFilePath);
                if (File.Exists(fullPath))
                {
                    return fullPath;
                }
            }

            // 如果直接路径找不到，尝试递归向上查找
            return FindJsonFileRecursive(jsonFilePath, searchPaths);
        }

        /// <summary>
        /// 递归向上查找JSON文件
        /// </summary>
        /// <param name="jsonFilePath">JSON文件路径</param>
        /// <param name="basePaths">基础搜索路径列表</param>
        /// <returns>找到的完整文件路径，如果找不到则返回null</returns>
        private static string FindJsonFileRecursive(string jsonFilePath, List<string> basePaths)
        {
            foreach (string basePath in basePaths)
            {
                DirectoryInfo currentDir = new DirectoryInfo(basePath);
                
                // 向上递归查找，最多查找10层目录
                for (int level = 0; level < 10; level++)
                {
                    if (currentDir == null || !currentDir.Exists)
                        break;

                    string fullPath = Path.Combine(currentDir.FullName, jsonFilePath);
                    if (File.Exists(fullPath))
                    {
                        return fullPath;
                    }

                    // 移动到上级目录
                    currentDir = currentDir.Parent;
                }
            }

            return null;
        }

        /// <summary>
        /// 将实例数据保存到JSON文件
        /// </summary>
        /// <param name="instance">要保存的实例</param>
        /// <returns>是否成功保存</returns>
        public static bool SaveInstanceToJson(object instance)
        {
            try
            {
                if (instance == null)
                {
                    return false;
                }

                TypeConfiguration config = LoadConfig();

                // 检查JSON文件路径是否有效
                if (string.IsNullOrEmpty(config.JsonFilePath))
                {
                    return false;
                }

                // 查找JSON文件的完整路径
                string jsonFilePath = FindJsonFile(config.JsonFilePath);
                
                // 如果找不到文件，使用配置中的路径作为默认保存位置
                if (string.IsNullOrEmpty(jsonFilePath))
                {
                    jsonFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.JsonFilePath);
                }

                // 确保目录存在
                string directory = Path.GetDirectoryName(jsonFilePath);
                if (!string.IsNullOrEmpty(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                // 将对象序列化为JSON字符串
                string jsonContent = JsonConvert.SerializeObject(instance, Formatting.Indented);

                // 保存到文件，使用UTF-8编码（无BOM）
                File.WriteAllText(jsonFilePath, jsonContent, new System.Text.UTF8Encoding(false));

                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存到JSON文件时出错: {ex.Message}", "JSON序列化错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        /// <summary>
        /// 保存配置到文件
        /// </summary>
        /// <param name="config">要保存的配置</param>
        /// <returns>是否成功保存</returns>
        public static bool SaveConfig(TypeConfiguration config)
        {
            try
            {
                if (config == null)
                {
                    return false;
                }

                string configFolderPath = GetConfigFolderPath();
                string configFilePath = Path.Combine(configFolderPath, ConfigFileName);

                // 确保目录存在
                Directory.CreateDirectory(configFolderPath);

                // 将配置序列化为JSON字符串
                string jsonContent = JsonConvert.SerializeObject(config, Formatting.Indented);

                // 保存到文件，使用UTF-8编码（无BOM）
                File.WriteAllText(configFilePath, jsonContent, new System.Text.UTF8Encoding(false));

                // 更新缓存
                _config = config;
                _currentConfigFile = configFilePath;

                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存配置文件时出错: {ex.Message}", "配置保存错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }
    }
}